package com.fangda.network.tcp;

import com.fangda.network.AbstractNetwork;
import com.fangda.network.NetworkConfig;
import com.fangda.network.NetworkMessage;
import com.fangda.network.NetworkMessageCallback;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetSocket;
import io.vertx.core.parsetools.RecordParser;

import java.util.List;

public abstract class AbstractTcpNetwork extends AbstractNetwork {
    /**
	 * 
	 */
	private static final long serialVersionUID = -7444041267644345693L;

    public AbstractTcpNetwork(String id, NetworkConfig config) {
        super(id, config);
    }

    public void send(NetSocket socket, NetworkMessage message, NetworkMessageCallback messageCallback) {
        socket.write(Buffer.buffer(message.getPayload()), res -> {
            if(messageCallback != null) {
                messageCallback.callback(res, socket.remoteAddress());
            }
        });
    }

    /**
     * 粘包处理
     * @param network
     * @param config
     * @return
     */
    protected RecordParser getRecordParse(AbstractTcpNetwork network, NetworkConfig config) {
        RecordParser parser = null;
        SplitType splitType = (SplitType)config.getConfig().get("splitType");
        if(splitType == SplitType.FIXED_LENTH) {
            int size = (int)config.getConfig().get("fixLength");
            parser = RecordParser.newFixed(size);
        } else if(splitType == SplitType.LINE_BASE) {
            parser = RecordParser.newDelimited("\r");
        } else if(splitType == SplitType.DELIMITER_BASE) {
            parser = RecordParser.newDelimited((String)config.getConfig().get("delimiterChar"));
        }
        return parser;
    }

    /**
     * TCP消息处理
     * @param buffer
     * @param config
     */
    protected void handleMessage(Buffer buffer, NetworkConfig config) {
        byte[] bytes = buffer.getBytes();
        if(config.getParser() != null) {
            config.getParser().decode(new NetworkMessage(bytes, null));
        }
    }

    protected void initSocket(NetSocket socket, List<NetSocket> sessions) {
        RecordParser recordParse = getRecordParse(this, config);
        if(recordParse == null) {
            socket.handler(buffer -> {
                handleMessage(buffer, config);
            });
        } else {
            recordParse.setOutput(buffer -> {
                handleMessage(buffer, config);
            });
            socket.handler(recordParse);
        }
        socket.closeHandler(v -> {
            setAlive(false);
            if(sessions != null) {
                sessions.remove(socket);
            }
            if(callback != null) {
                callback.connectionChange(false, null);
            }
        });
        socket.exceptionHandler(v -> {
            if(callback != null) {
                callback.exceptionHandler(v);
            }
        });
    }

}
